package ua_gov_energy_vkek_icelineacct.service;

import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import ua_gov_energy_vkek_icelineacct.model.User;

/**
 * @author moroz
 */
@Stateless()
public class UsersFacade extends AbstractFacade<User> {

    @PersistenceContext(name = "radius")
    private EntityManager em;

    public UsersFacade() {
        super(User.class);
    }

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    /**
     * @param enabled one of (y|n)
     * @param userGroup like (speed-XXX)
     * @param range - диапазон выборки
     * @return список пользователей с применением фильтров enabled & userGroup
     */
    public List<User> listByParams(String enabled, String userGroup, int[] range) {

        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery cq = cb.createQuery();
        Root<User> u = cq.from(User.class);

        Predicate enabledLP = likePredicate(cb, u, "enabled", enabled);
        Predicate userGroupLP = likePredicate(cb, u, "userGroup", userGroup);
        Predicate and = and(cb, enabledLP, userGroupLP);
        cq.select(u).where(and);


        Query q = getEntityManager().createQuery(cq);
        if ((range != null) && (range.length == 2)) {
            q.setMaxResults(range[1] - range[0]);
            q.setFirstResult(range[0]);
        }
        return q.getResultList();

    }

    private Predicate likePredicate(CriteriaBuilder cb, Path path, String attrName, String attrValue) {
        if (attrValue != null) {
            return cb.like(path.<String>get(attrName), attrValue);
        } else {
            return null;
        }

    }
    /*
     * Стандартный метод CriteriaBuilder.and(Predicate...) выдает ошибку
     * в случае, если один из предикатов null
     */

    private Predicate and(CriteriaBuilder cb, Predicate... restrictions) {

        ArrayList<Predicate> notNullPredicates = new ArrayList();
        int i = 0;
        for (Predicate p : restrictions) {
            if (p != null) {
                i++;
                notNullPredicates.add(p);
            }
        }

        return cb.and(notNullPredicates.toArray(new Predicate[0]/*creates new array with size of list elements*/));
    }
}
